#pragma once
#include <iostream>
#include <string>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>
int key = ftok(".", 'A');
#define EXIT_ERROR(m)       \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)
class shm
{
public:
    shm(int key, std::string name)
        : _key(key),
          _name(name)
    {
        // 创建共享内存
        if (_name == "Create")
        {
            _shmid = shmget(_key, 4096, IPC_CREAT | IPC_EXCL | 0666); // 如果是创建者，就需要创建共享内存
        }
        else if (_name == "User")
        {
            _shmid = shmget(_key, 4096, IPC_CREAT); // 如果是用户，就只需要获取该内存就行了，通过_key来获取相同的内存资源
        }
        if (_shmid < 0)
        {
            EXIT_ERROR("shmget");
        }
        std::cout << "create 成功" << std::endl;
        // 与进程建立联系,建立映射关系
        _addr = shmat(_shmid, nullptr, 0); // 成功返回映射地址，失败返回-1
        if (_addr == (void *)-1)
        {
            EXIT_ERROR("shmat");
        }
    }
    void *getAddr()
    {
        return _addr;
    }
    ~shm()
    {
        // 先取消共享内存与进程的联系
        int ret = shmdt(_addr);
        if (ret < 0)
        {
            //EXIT_ERROR("shmdt");
        }
        if (_name == "Create")
        {

            // 再删除共享内存
            int tem = shmctl(_shmid, IPC_RMID, nullptr);
            if (tem < 0)
            {
                EXIT_ERROR("shmctl");
            }
        }
    }

private:
    int _key;
    int _shmid;        // 共享内存标识符
    std::string _name; // 使用者
    void *_addr;       // 映射虚拟地址
};